package com.author.util;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.author.document.model.DocumentService;

/**
 * ServiceRegister class is the central class where every object that needs a particular type of service register itself to receive
 * notifications from objects which will provide that service.
 * @author Michael Madhukalya
 */
public final class ServiceRegister {
	private static final Map<Object, List<Object>> serviceMap = new HashMap<Object, List<Object>> ();
	private static ServiceRegister serviceRegister = null;
	private static final Object[] listofService = new Object[] {DocumentService.DOCUMENT_SERVICE};
	
	private ServiceRegister () {
		for (Object o : ServiceRegister.listofService) {
			ServiceRegister.serviceMap.put(o, null);
		}
	}
	
	/** Static Factory to instantiate a ServiceRegister type object */
	public final static ServiceRegister getServiceRegister () {
		synchronized (ServiceRegister.class) {
			if (ServiceRegister.serviceRegister == null) {
				ServiceRegister.serviceRegister = new ServiceRegister ();
			}
			return ServiceRegister.serviceRegister;
		}
	}
	
	/** Register a client to receive service from whoever provides the service */
	public final void registerForService (Object serviceName, Object client) throws Exception {
		if (serviceName == null) {
			String fmtExceptionMsg = "Service Name can't be null";
			throw new Exception (fmtExceptionMsg);
		}
		
		if (client == null) {
			String fmtExceptionMsg = "Client name can't be null";
			throw new Exception (fmtExceptionMsg);
		}
		
		if (!ServiceRegister.serviceMap.containsKey(serviceName)) {
			String fmtExceptionMsg = "Service can't be located inside Service Register";
			throw new Exception (fmtExceptionMsg);
		}
		
		List<Object> clientList = ServiceRegister.serviceMap.get(serviceName);
		if (clientList == null) {
			clientList = new LinkedList<Object> ();
			ServiceRegister.serviceMap.put(serviceName, clientList);
		}
		
		clientList.add(client);
	}
	
	/** Returns a list of service listeners for that particular service */
	public final List<Object> getClientsForService (Object serviceName) throws Exception {
		if (serviceName == null) {
			String fmtExceptionMsg = "Service Name can't be null";
			throw new Exception (fmtExceptionMsg);
		}
		
		if (!ServiceRegister.serviceMap.containsKey(serviceName)) {
			String fmtExceptionMsg = "Service can't be located inside Service Register";
			throw new Exception (fmtExceptionMsg);
		}
		
		return ServiceRegister.serviceMap.get(serviceName);
	}
}
